/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package models;
import core.threads.DataBase;
import cstAndEnum.CARA;
import java.util.ArrayList;
import myTest.MYTest;
import java.util.List;
import models.Card.Card;
import models.Deck.Deck;

/**
 * 游戏
 * @author Invince
 */
public class Game {
/*----------Attributs-------------------*/
    /**
     * 玩家列表
     */
    protected ListPlayer listPlayer;//ListPlayer id=1
    /**
     * 主公的ID
     */
    protected int majestyID;
    /**
     * 摸牌堆
     */
    protected Deck baseDeck;//Deck id=1
    /**
     * 弃牌堆
     */
    protected Deck abandonDeck;//Deck id=2
    /**
     * 死亡的玩家
     */
    protected ListPlayer listDiePlayer;//ListPlayer id=2

    /**
     * 牌的索引，加速查询用
     */
    protected List<CardInfo> listCardInfo;//按照牌的id排列
    public static class CardInfo{
        /**
         * -1表示server, 其他未playerList加入时的id
         */
        protected int idOwner;
        /**
         * 是player的话，1表示手牌，2装备，3状态。Server(game)的话1是摸牌库，2是弃牌库
         */
        protected int idDeck;
        public int getIdDeck() {return idDeck;}
        public void setIdDeck(int idDeck) {this.idDeck = idDeck;}
        public int getIdOwner() {return idOwner;}
        public void setIdOwner(int idOwner) {this.idOwner = idOwner;}
        public CardInfo(int idOwner, int idDeck) {
            this.idOwner = idOwner;
            this.idDeck = idDeck;
        }
        public CardInfo(){this.idDeck=0;this.idOwner=0;}
     }

/*----------Public functions------------*/
    /**
     * 通过idPlayer找到player
     * @param idPlayer
     * @return
     */
    public Player getPlayerByID(int idPlayer){
        if(idPlayer==-1){//表示是Server
            return null;
        }else{
            Player temp=this.listPlayer.findPlayerById(idPlayer);
            if(!temp.equals(null)){
                return temp;
            }else{
                temp=this.listDiePlayer.findPlayerById(idPlayer);
                if(temp.equals(null)){
                    MYTest.println("Error:getPlayerByID player id error!");
                }
                return temp;
            }
            
        }
    }


    /**
     * 通过idOwner和idDeck找到Deck
     * @param idOwner
     * @param idDeck
     * @return
     */
    public Deck getDeckByID(int idOwner, int idDeck){
         if(idOwner==-1){//表示是Server
                if(idDeck==1){
                    return this.baseDeck;
                }else if(idDeck==2){
                    return this.abandonDeck;
                }else{
                    MYTest.println("Error: getDeck, Deck of which id equals "+idDeck+" doesn't exist in Server!");
                    return null;
                }
            }else{
                Player temp=getPlayerByID(idOwner);
                if(!temp.equals(null)){
                    if(idDeck==1){
                        return temp.getDeckPlayer();
                    }else if(idDeck==2){
                        return temp.getDeckEqp();
                    }else if(idDeck==3){
                        return temp.getDeckBuff();
                    }else{
                        MYTest.println("Error:getDeck, Deck of which id equals "+idDeck+" doesn't exist in Player!");
                        return null;
                    }
                }else{
                    MYTest.println("Error: getDeck, Player id error!");
                    return null;
                }
            }
    }


    /**
     * 返回idCard牌的拥有者，null表示Server
     * @param idCard
     * @return
     */
    public Player getOwnerOfCard(int idCard){
        int idOwner=listCardInfo.get(idCard).getIdOwner();
        return getPlayerByID(idOwner);
    }

    /**
     * 返回idCard所在的牌库
     * @param idCard
     * @return
     */
    public Deck getDeckOfCard(int idCard){
        int idOwner=listCardInfo.get(idCard).getIdOwner();
        int idDeck=listCardInfo.get(idCard).getIdDeck();
        return getDeckByID(idOwner, idDeck);
    }



    /**
     * 从targetId的targetDeckId,取第indexCard张牌到sourceId的SourceDeckId (这个方法可能要舍弃掉)
     * @param sourceId
     * @param sourceDeckId
     * @param targetId
     * @param targetDeckId
     * @param indexCard
     */
    public void drawCard(int sourceId,int sourceDeckId,int targetId,int targetDeckId,int indexCard){
        Deck sourceDeck=getDeckByID(sourceId,sourceDeckId);
        Deck targetDeck=getDeckByID(targetId, targetDeckId);
        if(sourceDeck.equals(null) || targetDeck.equals(null)){
            MYTest.println("Error: drawCard , deck error!");
            return;
        }else{
            if(targetDeck.size()>indexCard){
                //更新索引
                int idCard=targetDeck.get(indexCard).getId();
                this.listCardInfo.get(idCard).setIdDeck(sourceDeckId);
                this.listCardInfo.get(idCard).setIdOwner(sourceId);
                //移动牌
                sourceDeck.drawCard(indexCard, targetDeck);
            }else{
                MYTest.println("Error: drawCard, indexCard error!");
            }
        }
    }


    /**
     * 从targetId的targetDeckId,
     * @param sourceId
     * @param sourceDeckId
     * @param idxCard
     */
 /**
     * 从targetId的targetDeckId,
     * @param sourceId
     * @param sourceDeckId
     * @param idxCard
     */
    public void drawCard(int sourceId,int sourceDeckId,int idCard){
        int targetId=this.listCardInfo.get(idCard).getIdOwner();
        int targetDeckId=this.listCardInfo.get(idCard).getIdDeck();
        Deck sourceDeck=getDeckByID(sourceId,sourceDeckId);
        Deck targetDeck=getDeckByID(targetId, targetDeckId);
        int indexCard=-1;
        for(int i=0;i<targetDeck.size();i++){
            if(targetDeck.get(i).getId()==idCard){
                indexCard=i;
                break;
            }
        }
        if(indexCard==-1){
            MYTest.println("Error: drawCard error, impossible error!");
            return ;
        }else{
            drawCard(sourceId, sourceDeckId, targetId, targetDeckId, indexCard);
        }
    }

    /**
     * 从摸牌库里摸牌
     * @param sourceId
     * @param nbCard
     */
    public void drawCardFromBaseDeck(int sourceId,int nbCard){
        int sizeBaseDeck=this.baseDeck.size();
        if(nbCard>(sizeBaseDeck+this.abandonDeck.size())){
            MYTest.println("Error: drawCardFromBaseDeck, nbCard Error");
        }
        if(nbCard>=sizeBaseDeck){//将弃牌库，洗好后，置于现有摸牌库下
            //处理Card索引
            for(Card card:this.abandonDeck.getListCard()){
                this.listCardInfo.get(card.getId()).setIdDeck(1);//1为摸牌库
            }
            this.abandonDeck.shuffle();
            this.baseDeck.getListCard().addAll(this.abandonDeck.getListCard());
            this.abandonDeck=new Deck(2);//2为弃牌库
        }
        //处理索引
        for(int i=0;i<nbCard;i++){
            int idCard=this.baseDeck.get(i).getId();
            this.listCardInfo.get(idCard).setIdOwner(sourceId);
            this.listCardInfo.get(idCard).setIdDeck(1);//总是手牌库
        }
        //移牌
        Deck sourceDeck=getDeckByID(sourceId, 1/*总是手牌库*/);
        sourceDeck.drawCardFromBaseDeck(nbCard, sourceDeck);
    }


    /**
     * 玩家死亡  这个函数还有问题，牌的移动没写，应该将所有牌移到弃牌库
     * @param idPlayer
     * @return
     */
    public void playerDie(int idPlayer){
        Player player=getPlayerByID(idPlayer);
        if(player.equals(null)){//一般不会出现
            MYTest.println("Error:playerDie , idPlayer not found!");
            return;
        }
        player=this.listDiePlayer.findPlayerById(idPlayer);
        if(!player.equals(null)){//一般不会出现
            MYTest.println("Error:playerDie, he is already dead");
            return;
        }
        player=this.listPlayer.findPlayerById(idPlayer);
        if(!player.equals(null)){
            MYTest.println("PlayerDie : "+player.getName()+" dies.");
            this.listPlayer.getList().remove(player);
            this.listDiePlayer.getList().add(player);

            //弃掉该玩家所有的牌，处理索引
            for(Card card:player.getDeckPlayer().getListCard()){
                this.listCardInfo.get(card.getId()).setIdOwner(-1);//Server
                this.listCardInfo.get(card.getId()).setIdDeck(2);//弃牌库
            }
            for(Card card:player.getDeckBuff().getListCard()){
                this.listCardInfo.get(card.getId()).setIdOwner(-1);//Server
                this.listCardInfo.get(card.getId()).setIdDeck(2);//弃牌库
            }
            for(Card card:player.getDeckEqp().getListCard()){
                this.listCardInfo.get(card.getId()).setIdOwner(-1);//Server
                this.listCardInfo.get(card.getId()).setIdDeck(2);//弃牌库
            }

            //判断游戏是否结束
            if(isGameOver()){
               settlement();//结算分数
            }
        }
    }


    /**
     * 判断游戏是否结束
     * @return
     */
    public boolean isGameOver(){
        int nbRebel=0;
        int nbSpy=0;
        for(Player player :this.listPlayer.getList()){
            if(player.getCara().equals(CARA.REBEL)){
                nbRebel++;
            }
            if(player.getCara().equals(CARA.SPY)){
                nbSpy++;
            }
        }
        if(!this.listDiePlayer.findPlayerById(majestyID).equals(null)){
            if(nbRebel==0){
                MYTest.println("Game is Over,the SPY win!");
            }else{
                MYTest.println("Game is Over, the Rebel win!");
            }
            return true;
        }
        if(nbRebel==0 && nbSpy==0){
            MYTest.println("Game is Over, the Majesty and the LOYAL win!");
            return true;
        }
        return false;
    }

    public void settlement(){
        MYTest.println("settelement : Not supported yet!");
        return;
    }

/*----------Private functions-----------*/
/*----------Constructor-----------------*/
    /**
     *
     * @param listPlayer 玩家列表
     * @param baseDeck   摸牌库
     */
    public Game(List<Player> listPlayer,int majestyID, Deck baseDeck) {
        this.listPlayer = new ListPlayer(1,listPlayer);//listPlayer id=1
        this.majestyID=majestyID;
        this.baseDeck = baseDeck;
        // 一个空的死亡了的玩家列表
        this.listDiePlayer=new ListPlayer(2);//listPlayer id=2
        // 一个空的弃牌库
        this.abandonDeck = new Deck(2);//Deck id=2
        this.listCardInfo=new ArrayList<CardInfo>(DataBase.dbCard.size());
    }

    public Game() {
        //初始化所有列表类参数
        this.abandonDeck=new Deck(2);//Deck id=2
        this.baseDeck=new Deck(1);//Deck id=1
        this.listDiePlayer=new ListPlayer(2);//listPlayer id=2
        this.listPlayer=new ListPlayer(1);//listPlayer id=1
        this.listCardInfo=new ArrayList<CardInfo>(DataBase.dbCard.size());
    }

/*----------Gets and sets---------------*/
    public Deck getBaseDeck() {
        return baseDeck;
    }

    public void setBaseDeck(Deck baseDeck) {
        this.baseDeck = baseDeck;
    }

    public ListPlayer getListPlayer() {
        return listPlayer;
    }

    public void setListPlayer(List<Player> listPlayer) {
        this.listPlayer.setList(listPlayer);
    }

    public Deck getAbandonDeck() {
        return abandonDeck;
    }

    public ListPlayer getListDiePlayer() {
        return listDiePlayer;
    }

    public int getMajestyID() {
        return majestyID;
    }

    public void setAbandonDeck(Deck abandonDeck) {
        this.abandonDeck = abandonDeck;
    }

    public void setListDiePlayer(ListPlayer listDiePlayer) {
        this.listDiePlayer = listDiePlayer;
    }

    public void setListPlayer(ListPlayer listPlayer) {
        this.listPlayer = listPlayer;
    }

    public void setMajestyID(int majestyID) {
        this.majestyID = majestyID;
    }

    public List<CardInfo> getListCardInfo() {
        return listCardInfo;
    }

    public void setListCardInfo(List<CardInfo> listCardInfo) {
        this.listCardInfo = listCardInfo;
    }
    
}
